package com.google.zxing.journeyapps.barcodescanner.camera;

import com.google.zxing.client.ohos.AmbientLightManager;
import com.google.zxing.journeyapps.barcodescanner.SourceData;
import ohos.agp.graphics.Surface;
import ohos.app.Context;
import ohos.media.camera.CameraKit;
import ohos.media.camera.device.Camera;
import ohos.media.camera.device.CameraStateCallback;
import ohos.media.camera.params.ParameterKey;
import ohos.media.image.ImagePacker;
import ohos.media.image.common.Size;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;

import java.io.IOException;

import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;

@PrepareForTest({CameraManager.class, CameraStateCallback.class, SourceData.class, ImagePacker.class, Size.class})
@RunWith(PowerMockRunner.class)
@SuppressStaticInitializationFor("com.google.zxing.journeyapps.barcodescanner.camera.CameraManager")
public class CameraManagerTestOs {
    CameraManager cameraManager;
    private Context context;

    @Before
    public void setUp() throws Exception {
        context = mock(Context.class);
        CameraStateCallback cameraStateCallback = mock(CameraStateCallback.class);
        PowerMockito.whenNew(CameraStateCallback.class).withAnyArguments().thenReturn(cameraStateCallback);
        cameraManager = new CameraManager(context);
    }

    @After
    public void tearDown() throws Exception {
    }

    @Test
    public void open() throws Exception {
        CameraKit cameraKit = mock(CameraKit.class);
        when(CameraKit.getInstance(context)).thenReturn(cameraKit);

        cameraManager.open();
        verify(cameraKit, times(1)).createCamera(anyString(), any(), any());
    }

    @Test
    public void configure() {
        cameraManager.configure();
        Size requestedPreviewSize = Whitebox.getInternalState(cameraManager, "requestedPreviewSize");
        Assert.assertNotNull(requestedPreviewSize);
    }

    @Test
    public void setPreviewDisplay() throws IOException {
        cameraManager.setPreviewDisplay(mock(Surface.class));
        Camera mCamera = Whitebox.getInternalState(cameraManager, "mCamera");
        verify(mCamera, times(1)).configure(any());
    }

    @Test
    public void testSetPreviewDisplay() throws IOException {
        cameraManager.setPreviewDisplay(mock(CameraSurface.class));
        Camera mCamera = Whitebox.getInternalState(cameraManager, "mCamera");
        verify(mCamera, times(1)).configure(any());
    }

    @Test
    public void startPreview() {
        cameraManager.startPreview(mock(CameraSurface.class));
        AmbientLightManager ambientLightManager = Whitebox.getInternalState(cameraManager, "ambientLightManager");
        verify(ambientLightManager, times(1)).start();
    }

    @Test
    public void stopPreview() {
        AutoFocusManager autoFocusManager = mock(AutoFocusManager.class);
        AmbientLightManager ambientLightManager = mock(AmbientLightManager.class);
        Camera mCamera = mock(Camera.class);
        Whitebox.setInternalState(cameraManager, "autoFocusManager", autoFocusManager);
        Whitebox.setInternalState(cameraManager, "ambientLightManager", ambientLightManager);
        Whitebox.setInternalState(cameraManager, "mCamera", mCamera);
        Whitebox.setInternalState(cameraManager, "previewing", true);
        cameraManager.stopPreview();

        boolean previewing = Whitebox.getInternalState(cameraManager, "previewing");
        Assert.assertEquals(false, previewing);
    }

    @Test
    public void close() {
        cameraManager.close();
        Camera mCamera = Whitebox.getInternalState(cameraManager, "mCamera");
        Assert.assertNull(mCamera);
    }

    @Test
    public void isCameraRotated() {
        boolean cameraRotated = cameraManager.isCameraRotated();
        Assert.assertEquals(false, cameraRotated);
    }

    @Test
    public void getCameraRotation() {
        int cameraRotation = cameraManager.getCameraRotation();
        Assert.assertEquals(-1, cameraRotation);

    }

    @Test
    public void isOpen() {
        boolean open = cameraManager.isOpen();
        Assert.assertEquals(false, open);
    }

    @Test
    public void getNaturalPreviewSize() {
        com.google.zxing.journeyapps.barcodescanner.Size naturalPreviewSize = cameraManager.getNaturalPreviewSize();
        Assert.assertNull(naturalPreviewSize);
    }

    @Test
    public void getPreviewSize() {
        com.google.zxing.journeyapps.barcodescanner.Size previewSize = cameraManager.getPreviewSize();
        Assert.assertNull(previewSize);
    }

    @Test
    public void requestPreviewFrame() {
        Camera mCamera = Mockito.mock(Camera.class);
        Whitebox.setInternalState(cameraManager, "mCamera", mCamera);
        Whitebox.setInternalState(cameraManager, "previewing", true);
        cameraManager.requestPreviewFrame(new PreviewCallback() {
            @Override
            public void onPreview(SourceData sourceData) {

            }

            @Override
            public void onPreviewError(Exception e) {

            }
        });
        verify(mCamera, times(1)).triggerLoopingCapture(any());
    }

    @Test
    public void getCameraSettings() {
        CameraSettings cameraSettings = cameraManager.getCameraSettings();
        Assert.assertNotNull(cameraSettings);
    }

    @Test
    public void setCameraSettings() {
        cameraManager.setCameraSettings(new CameraSettings());
        CameraSettings cameraSettings = cameraManager.getCameraSettings();
        Assert.assertNotNull(cameraSettings);
    }

    @Test
    public void getDisplayConfiguration() {
        DisplayConfiguration displayConfiguration = cameraManager.getDisplayConfiguration();
        Assert.assertNotNull(displayConfiguration);
    }

    @Test
    public void setDisplayConfiguration() {
        cameraManager.setDisplayConfiguration(new DisplayConfiguration(1));
        DisplayConfiguration displayConfiguration = cameraManager.getDisplayConfiguration();
        Assert.assertNotNull(displayConfiguration);
    }

    @Test
    public void setTorch() {
        Camera mCamera = Mockito.mock(Camera.class);
        Whitebox.setInternalState(cameraManager, "mCamera", mCamera);
        AutoFocusManager autoFocusManager = Mockito.mock(AutoFocusManager.class);
        Whitebox.setInternalState(cameraManager, "autoFocusManager", autoFocusManager);
        cameraManager.setTorch(true);
        verify(autoFocusManager, times(1)).start();
    }

    @Test
    public void changeCameraParameters() {
        Camera mCamera = Mockito.mock(Camera.class);
        Whitebox.setInternalState(cameraManager, "mCamera", mCamera);
        cameraManager.changeCameraParameters(new CameraParametersCallback() {
            @Override
            public ParameterKey changeCameraParameters(ParameterKey parameters) {
                return null;
            }
        });
    }

    @Test
    public void isTorchOn() {
        boolean torchOn = cameraManager.isTorchOn();
        Assert.assertEquals(false, torchOn);
    }

    @Test
    public void getCamera() {
        Camera camera = cameraManager.getCamera();
        Assert.assertNull(camera);
    }
}